@echo off
:: Node Exporter Windows安装脚本
:: 作者: Logan.Li
:: 功能: 自动下载、安装和配置Prometheus Node Exporter

setlocal enabledelayedexpansion

:: 配置变量
set "NODE_EXPORTER_VERSION=1.6.1"
set "DOWNLOAD_URL=https://github.com/prometheus/node_exporter/releases/download/v%NODE_EXPORTER_VERSION%/node_exporter-%NODE_EXPORTER_VERSION%.windows-amd64.tar.gz"
set "INSTALL_DIR=C:\Program Files\node_exporter"
set "SERVICE_NAME=NodeExporter"
set "TEMP_DIR=%TEMP%\node_exporter_install"

:: 颜色输出函数
call :info "开始安装 Node Exporter v%NODE_EXPORTER_VERSION%"

:: 检查管理员权限
call :check_admin
if errorlevel 1 (
    call :error "需要管理员权限运行此脚本"
    pause
    exit /b 1
)

:: 创建临时目录
if not exist "%TEMP_DIR%" mkdir "%TEMP_DIR%"
cd /d "%TEMP_DIR%"

:: 下载Node Exporter
call :info "正在下载 Node Exporter..."
call :download_node_exporter
if errorlevel 1 (
    call :error "下载失败"
    goto :cleanup
)

:: 解压文件
call :info "正在解压文件..."
call :extract_files
if errorlevel 1 (
    call :error "解压失败"
    goto :cleanup
)

:: 安装Node Exporter
call :info "正在安装 Node Exporter..."
call :install_node_exporter
if errorlevel 1 (
    call :error "安装失败"
    goto :cleanup
)

:: 创建Windows服务
call :info "正在创建Windows服务..."
call :create_service
if errorlevel 1 (
    call :error "服务创建失败"
    goto :cleanup
)

:: 启动服务
call :info "正在启动服务..."
call :start_service
if errorlevel 1 (
    call :error "服务启动失败"
    goto :cleanup
)

call :success "Node Exporter 安装完成！"
call :info "服务端口: 9100"
call :info "访问地址: http://localhost:9100/metrics"

goto :cleanup

:: 函数定义
:check_admin
net session >nul 2>&1
exit /b %errorlevel%

:download_node_exporter
:: 使用PowerShell下载文件
powershell -Command "& {[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; Invoke-WebRequest -Uri '%DOWNLOAD_URL%' -OutFile 'node_exporter.tar.gz'}"
if not exist "node_exporter.tar.gz" exit /b 1
exit /b 0

:extract_files
:: 使用PowerShell解压tar.gz文件
powershell -Command "& {Add-Type -AssemblyName System.IO.Compression.FileSystem; $stream = New-Object System.IO.FileStream('node_exporter.tar.gz', [System.IO.FileMode]::Open); $gzip = New-Object System.IO.Compression.GzipStream($stream, [System.IO.Compression.CompressionMode]::Decompress); $tar = New-Object System.IO.FileStream('node_exporter.tar', [System.IO.FileMode]::Create); $gzip.CopyTo($tar); $tar.Close(); $gzip.Close(); $stream.Close()}"
if errorlevel 1 exit /b 1

:: 解压tar文件
powershell -Command "& {$tar = [System.IO.File]::OpenRead('node_exporter.tar'); $buffer = New-Object byte[] 512; while($tar.Read($buffer, 0, 512) -gt 0) { $name = [System.Text.Encoding]::ASCII.GetString($buffer, 0, 100).TrimEnd([char]0); if($name -like '*/node_exporter.exe') { $tar.Seek(([Math]::Ceiling($tar.Position / 512) * 512), 'Begin'); $size = [Convert]::ToInt64([System.Text.Encoding]::ASCII.GetString($buffer, 124, 12).Trim(), 8); $output = [System.IO.File]::Create('node_exporter.exe'); $remaining = $size; while($remaining -gt 0) { $toRead = [Math]::Min(4096, $remaining); $read = $tar.Read($buffer, 0, $toRead); $output.Write($buffer, 0, $read); $remaining -= $read } $output.Close(); break } $tar.Seek(([Math]::Ceiling($tar.Position / 512) * 512), 'Begin') } $tar.Close()}"
if not exist "node_exporter.exe" exit /b 1
exit /b 0

:install_node_exporter
:: 创建安装目录
if not exist "%INSTALL_DIR%" mkdir "%INSTALL_DIR%"

:: 复制文件
copy "node_exporter.exe" "%INSTALL_DIR%\" >nul
if errorlevel 1 exit /b 1

:: 创建配置文件
echo # Node Exporter 配置文件 > "%INSTALL_DIR%\config.yml"
echo # 作者: Logan.Li >> "%INSTALL_DIR%\config.yml"

exit /b 0

:create_service
:: 停止现有服务（如果存在）
sc query "%SERVICE_NAME%" >nul 2>&1
if not errorlevel 1 (
    call :warn "发现现有服务，正在停止..."
    sc stop "%SERVICE_NAME%" >nul 2>&1
    sc delete "%SERVICE_NAME%" >nul 2>&1
    timeout /t 3 >nul
)

:: 创建新服务
sc create "%SERVICE_NAME%" binPath= "\"%INSTALL_DIR%\node_exporter.exe\"" DisplayName= "Prometheus Node Exporter" start= auto
if errorlevel 1 exit /b 1

:: 设置服务描述
sc description "%SERVICE_NAME%" "Prometheus Node Exporter - 系统指标收集器"
exit /b 0

:start_service
sc start "%SERVICE_NAME%" >nul
if errorlevel 1 exit /b 1

:: 等待服务启动
timeout /t 5 >nul

:: 检查服务状态
sc query "%SERVICE_NAME%" | find "RUNNING" >nul
if errorlevel 1 exit /b 1

exit /b 0

:cleanup
cd /d "%~dp0"
if exist "%TEMP_DIR%" rmdir /s /q "%TEMP_DIR%" >nul 2>&1
endlocal
pause
exit /b 0

:: 输出函数
:info
echo [INFO] %~1
exit /b 0

:warn
echo [WARN] %~1
exit /b 0

:error
echo [ERROR] %~1
exit /b 0

:success
echo [SUCCESS] %~1
exit /b 0